diff options
| author | Fuwn <[email protected]> | 2026-01-24 13:09:50 +0000 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2026-01-24 13:09:50 +0000 |
| commit | 396acf3bbbe00a192cb0ea0a9ccf91b1d8d2850b (patch) | |
| tree | b9df4ca6a70db45cfffbae6fdd7252e20fb8e93c /src/app/(main)/websites/[websiteId]/WebsiteNav.tsx | |
| download | umami-main.tar.xz umami-main.zip | |
Created from https://vercel.com/new
Diffstat (limited to 'src/app/(main)/websites/[websiteId]/WebsiteNav.tsx')
| -rw-r--r-- | src/app/(main)/websites/[websiteId]/WebsiteNav.tsx | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/src/app/(main)/websites/[websiteId]/WebsiteNav.tsx b/src/app/(main)/websites/[websiteId]/WebsiteNav.tsx new file mode 100644 index 0000000..ad05b70 --- /dev/null +++ b/src/app/(main)/websites/[websiteId]/WebsiteNav.tsx @@ -0,0 +1,180 @@ +import { Column, Text } from '@umami/react-zen'; +import { SideMenu } from '@/components/common/SideMenu'; +import { useMessages, useNavigation } from '@/components/hooks'; +import { + AlignEndHorizontal, + ChartPie, + Clock, + Eye, + Sheet, + Tag, + User, + UserPlus, +} from '@/components/icons'; +import { WebsiteSelect } from '@/components/input/WebsiteSelect'; +import { Funnel, Lightning, Magnet, Money, Network, Path, Target } from '@/components/svg'; + +export function WebsiteNav({ + websiteId, + onItemClick, +}: { + websiteId: string; + onItemClick?: () => void; +}) { + const { formatMessage, labels } = useMessages(); + const { pathname, renderUrl, teamId, router } = useNavigation(); + + const renderPath = (path: string) => + renderUrl(`/websites/${websiteId}${path}`, { + event: undefined, + compare: undefined, + view: undefined, + }); + + const items = [ + { + label: formatMessage(labels.traffic), + items: [ + { + id: 'overview', + label: formatMessage(labels.overview), + icon: <Eye />, + path: renderPath(''), + }, + { + id: 'events', + label: formatMessage(labels.events), + icon: <Lightning />, + path: renderPath('/events'), + }, + { + id: 'sessions', + label: formatMessage(labels.sessions), + icon: <User />, + path: renderPath('/sessions'), + }, + { + id: 'realtime', + label: formatMessage(labels.realtime), + icon: <Clock />, + path: renderPath('/realtime'), + }, + { + id: 'compare', + label: formatMessage(labels.compare), + icon: <AlignEndHorizontal />, + path: renderPath('/compare'), + }, + { + id: 'breakdown', + label: formatMessage(labels.breakdown), + icon: <Sheet />, + path: renderPath('/breakdown'), + }, + ], + }, + { + label: formatMessage(labels.behavior), + items: [ + { + id: 'goals', + label: formatMessage(labels.goals), + icon: <Target />, + path: renderPath('/goals'), + }, + { + id: 'funnel', + label: formatMessage(labels.funnels), + icon: <Funnel />, + path: renderPath('/funnels'), + }, + { + id: 'journeys', + label: formatMessage(labels.journeys), + icon: <Path />, + path: renderPath('/journeys'), + }, + { + id: 'retention', + label: formatMessage(labels.retention), + icon: <Magnet />, + path: renderPath('/retention'), + }, + ], + }, + { + label: formatMessage(labels.audience), + items: [ + { + id: 'segments', + label: formatMessage(labels.segments), + icon: <ChartPie />, + path: renderPath('/segments'), + }, + { + id: 'cohorts', + label: formatMessage(labels.cohorts), + icon: <UserPlus />, + path: renderPath('/cohorts'), + }, + ], + }, + { + label: formatMessage(labels.growth), + items: [ + { + id: 'utm', + label: formatMessage(labels.utm), + icon: <Tag />, + path: renderPath('/utm'), + }, + { + id: 'revenue', + label: formatMessage(labels.revenue), + icon: <Money />, + path: renderPath('/revenue'), + }, + { + id: 'attribution', + label: formatMessage(labels.attribution), + icon: <Network />, + path: renderPath('/attribution'), + }, + ], + }, + ]; + + const handleChange = (value: string) => { + router.push(renderUrl(`/websites/${value}`)); + }; + + const renderValue = (value: any) => { + return ( + <Text truncate style={{ maxWidth: 160, lineHeight: 1 }}> + {value?.selectedItem?.name} + </Text> + ); + }; + + const selectedKey = items + .flatMap(e => e.items) + .find(({ path }) => path && pathname.endsWith(path.split('?')[0]))?.id; + + return ( + <Column padding="3" position="sticky" top="0" gap> + <WebsiteSelect + websiteId={websiteId} + teamId={teamId} + onChange={handleChange} + renderValue={renderValue} + buttonProps={{ style: { outline: 'none' } }} + /> + <SideMenu + items={items} + selectedKey={selectedKey} + allowMinimize={false} + onItemClick={onItemClick} + /> + </Column> + ); +} |